#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
基础抽象类
定义交易框架的核心抽象接口
"""

from abc import ABC, abstractmethod
from typing import Dict, Any, Optional, List
from datetime import datetime
import asyncio

from utils.logger import get_logger
from utils.exceptions import TqSdkTraderError


class BaseComponent(ABC):
    """基础组件类"""

    def __init__(self, name: str = None):
        self.name = name or self.__class__.__name__
        self.logger = get_logger(self.name)
        self._initialized = False
        self._running = False

    @abstractmethod
    async def initialize(self):
        """初始化组件"""
        pass

    @abstractmethod
    async def cleanup(self):
        """清理资源"""
        pass

    async def start(self):
        """启动组件"""
        if not self._initialized:
            await self.initialize()
            self._initialized = True

        self._running = True
        self.logger.info(f"{self.name} 启动成功")

    async def stop(self):
        """停止组件"""
        self._running = False
        await self.cleanup()
        self.logger.info(f"{self.name} 停止成功")

    @property
    def is_running(self) -> bool:
        """检查组件是否正在运行"""
        return self._running

    @property
    def is_initialized(self) -> bool:
        """检查组件是否已初始化"""
        return self._initialized


class BaseDataProvider(ABC):
    """数据提供者基础类"""

    def __init__(self, symbol: str):
        self.symbol = symbol
        self.logger = get_logger(f"DataProvider.{symbol}")
        self._data_cache = {}
        self._subscribers = []

    @abstractmethod
    async def get_quote(self) -> Dict[str, Any]:
        """获取实时行情"""
        pass

    @abstractmethod
    async def get_kline_data(self, period: int, length: int) -> Dict[str, Any]:
        """获取K线数据"""
        pass

    @abstractmethod
    async def get_tick_data(self, length: int) -> Dict[str, Any]:
        """获取Tick数据"""
        pass

    def subscribe(self, callback):
        """订阅数据更新"""
        self._subscribers.append(callback)

    def unsubscribe(self, callback):
        """取消订阅"""
        if callback in self._subscribers:
            self._subscribers.remove(callback)

    async def _notify_subscribers(self, data_type: str, data: Any):
        """通知订阅者"""
        for callback in self._subscribers:
            try:
                await callback(data_type, data)
            except Exception as e:
                self.logger.error(f"通知订阅者失败: {e}")


class BaseStrategy(ABC):
    """策略基础类"""

    def __init__(self, symbol: str, config: Dict[str, Any]):
        self.symbol = symbol
        self.config = config
        self.logger = get_logger(f"Strategy.{symbol}")

        # 策略状态
        self.position = 0  # 当前持仓
        self.entry_price = None  # 开仓价格
        self.last_signal = None  # 最后信号

        # 策略统计
        self.total_trades = 0
        self.winning_trades = 0
        self.total_pnl = 0.0

    @abstractmethod
    async def initialize(self):
        """初始化策略"""
        pass

    @abstractmethod
    async def on_quote_update(self, quote: Dict[str, Any]):
        """行情更新回调"""
        pass

    @abstractmethod
    async def on_kline_update(self, kline: Dict[str, Any]):
        """K线更新回调"""
        pass

    @abstractmethod
    async def generate_signal(self) -> Optional[str]:
        """生成交易信号"""
        pass

    @abstractmethod
    async def calculate_position_size(self) -> int:
        """计算仓位大小"""
        pass

    async def update_statistics(self, trade_result: Dict[str, Any]):
        """更新策略统计"""
        self.total_trades += 1

        if trade_result.get('pnl', 0) > 0:
            self.winning_trades += 1

        self.total_pnl += trade_result.get('pnl', 0)

    def get_statistics(self) -> Dict[str, Any]:
        """获取策略统计信息"""
        win_rate = self.winning_trades / self.total_trades if self.total_trades > 0 else 0

        return {
            'total_trades': self.total_trades,
            'winning_trades': self.winning_trades,
            'win_rate': win_rate,
            'total_pnl': self.total_pnl,
            'position': self.position,
            'entry_price': self.entry_price
        }


class BaseRiskManager(ABC):
    """风险管理器基础类"""

    def __init__(self, config: Dict[str, Any]):
        self.config = config
        self.logger = get_logger("RiskManager")

        # 风险状态
        self.daily_pnl = 0.0
        self.daily_start_time = datetime.now().date()
        self.last_reset_date = datetime.now().date()

    @abstractmethod
    async def check_position_risk(self, symbol: str, position: int, entry_price: float, current_price: float) -> Dict[str, Any]:
        """检查持仓风险"""
        pass

    @abstractmethod
    async def check_daily_risk(self, current_pnl: float) -> bool:
        """检查日风险"""
        pass

    @abstractmethod
    async def calculate_stop_loss_price(self, entry_price: float, direction: str) -> float:
        """计算止损价格"""
        pass

    @abstractmethod
    async def calculate_take_profit_price(self, entry_price: float, direction: str) -> float:
        """计算止盈价格"""
        pass

    async def reset_daily_stats(self):
        """重置日统计"""
        current_date = datetime.now().date()
        if current_date != self.last_reset_date:
            self.daily_pnl = 0.0
            self.last_reset_date = current_date
            self.logger.info(f"重置日统计: {current_date}")


class BaseOrderManager(ABC):
    """订单管理器基础类"""

    def __init__(self, api_client):
        self.api_client = api_client
        self.logger = get_logger("OrderManager")
        self.active_orders = {}
        self.completed_orders = []

    @abstractmethod
    async def place_order(self, symbol: str, direction: str, offset: str, volume: int, price: Optional[float] = None) -> str:
        """下单"""
        pass

    @abstractmethod
    async def cancel_order(self, order_id: str) -> bool:
        """撤单"""
        pass

    @abstractmethod
    async def get_order_status(self, order_id: str) -> Dict[str, Any]:
        """获取订单状态"""
        pass

    @abstractmethod
    async def get_active_orders(self, symbol: Optional[str] = None) -> List[Dict[str, Any]]:
        """获取活跃订单"""
        pass

    async def cleanup_completed_orders(self):
        """清理已完成的订单"""
        # 将已完成的订单从活跃订单移到完成订单列表
        completed_ids = []
        for order_id, order in self.active_orders.items():
            if order.get('status') in ['FINISHED', 'CANCELLED']:
                self.completed_orders.append(order)
                completed_ids.append(order_id)

        for order_id in completed_ids:
            del self.active_orders[order_id]

        if completed_ids:
            self.logger.info(f"清理完成订单: {len(completed_ids)} 个")


class BaseTradingEngine(ABC):
    """交易引擎基础类"""

    def __init__(self, config: Dict[str, Any]):
        self.config = config
        self.logger = get_logger("TradingEngine")

        # 组件
        self.api_client = None
        self.data_provider = None
        self.strategy = None
        self.risk_manager = None
        self.order_manager = None

        # 状态
        self.is_running = False
        self.start_time = None

    @abstractmethod
    async def initialize(self):
        """初始化引擎"""
        pass

    @abstractmethod
    async def start_trading(self):
        """开始交易"""
        pass

    @abstractmethod
    async def stop_trading(self):
        """停止交易"""
        pass

    @abstractmethod
    async def process_quote_update(self, symbol: str, quote: Dict[str, Any]):
        """处理行情更新"""
        pass

    @abstractmethod
    async def process_kline_update(self, symbol: str, kline: Dict[str, Any]):
        """处理K线更新"""
        pass

    @abstractmethod
    async def execute_signal(self, signal: str):
        """执行交易信号"""
        pass

    async def health_check(self) -> Dict[str, Any]:
        """健康检查"""
        return {
            'is_running': self.is_running,
            'uptime': (datetime.now() - self.start_time).total_seconds() if self.start_time else 0,
            'strategy_stats': self.strategy.get_statistics() if self.strategy else {},
            'active_orders_count': len(self.order_manager.get_active_orders()) if self.order_manager else 0
        }


class BasePerformanceMonitor(ABC):
    """性能监控器基础类"""

    def __init__(self, config: Dict[str, Any]):
        self.config = config
        self.logger = get_logger("PerformanceMonitor")

        # 性能指标
        self.start_time = datetime.now()
        self.metrics = {
            'total_requests': 0,
            'successful_requests': 0,
            'failed_requests': 0,
            'average_response_time': 0.0,
            'total_trades': 0,
            'winning_trades': 0,
            'total_pnl': 0.0
        }

    @abstractmethod
    async def record_request(self, response_time: float, success: bool):
        """记录API请求"""
        pass

    @abstractmethod
    async def record_trade(self, trade_info: Dict[str, Any]):
        """记录交易"""
        pass

    @abstractmethod
    async def generate_report(self) -> Dict[str, Any]:
        """生成性能报告"""
        pass

    @abstractmethod
    async def check_performance_thresholds(self) -> List[str]:
        """检查性能阈值"""
        pass

    def get_uptime(self) -> float:
        """获取运行时间"""
        return (datetime.now() - self.start_time).total_seconds()

    def get_summary(self) -> Dict[str, Any]:
        """获取性能摘要"""
        uptime = self.get_uptime()
        success_rate = (self.metrics['successful_requests'] / self.metrics['total_requests']
                       if self.metrics['total_requests'] > 0 else 0)

        return {
            'uptime_seconds': uptime,
            'uptime_hours': uptime / 3600,
            'success_rate': success_rate,
            'total_requests': self.metrics['total_requests'],
            'average_response_time': self.metrics['average_response_time'],
            'total_trades': self.metrics['total_trades'],
            'win_rate': (self.metrics['winning_trades'] / self.metrics['total_trades']
                        if self.metrics['total_trades'] > 0 else 0),
            'total_pnl': self.metrics['total_pnl']
        }
